//
//  LazyProxy.m
//  ObjectCProject
//
//  Created by lvfeijun on 2021/5/21.
//

#import "LazyInitialization.h"

@interface LazyProxy : NSProxy

- (instancetype)initWithClass:(Class)class;

@end


@implementation LazyInitialization

+ (instancetype)lazy {
    return (id)[[LazyProxy alloc] initWithClass:[self class]];
}
- (instancetype)initWithClass:(Class)class{
    return (id)[[LazyProxy alloc] initWithClass: class];

}

-(void)say{
    NSLog(@"doSomething");
}


@end

@implementation LazyProxy{
    id _object;// 代理对象
    Class _objectClass;// 代理类
    NSInvocation *_initInvocation;// 自定义 init 调用
}

#pragma mark 初始化只存类型，并没有初始化


- (instancetype)initWithClass:(Class)cls {
    _objectClass = cls;
    return self;
}
- (void)instantiateObject {
    _object = [_objectClass alloc];
    if (_initInvocation == nil) {// 允许一些类 [SomeClass lazy] (没有调用 init)
        _object = [_object init];
    } else {// 调用自定义 init 方法
        [_initInvocation invokeWithTarget:_object];
        [_initInvocation getReturnValue:&_object];
        _initInvocation = nil;
    }
}

#pragma mark 消息转发的时候再去创建

- (id)forwardingTargetForSelector:(SEL)selector {
    if (_object == nil) {// _object 没有初始化
        NSLog(@"init");
        
        if (![NSStringFromSelector(selector) hasPrefix:@"init"]) {// 调用 init 开头之外的方法前进行 _object 初始化
            [self instantiateObject];
        }
    }
    return _object;// 将消息转发给 _object
}
// 调用自定义 init 方法会进入这个方法
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    NSMethodSignature *signature = [_objectClass instanceMethodSignatureForSelector:selector];
    return signature;
}
// 保存自定义 init 方法的调用
- (void)forwardInvocation:(NSInvocation *)invocation {
    _initInvocation = invocation;
}

@end
